package com.tarena.lbs.business.servcie.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.attach.pojo.param.PicUpdateParam;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.business.api.BusinessApi;
import com.tarena.lbs.business.api.pojo.BusinessDto;
import com.tarena.lbs.business.base.exception.BusinessServiceException;
import com.tarena.lbs.business.base.response.StatusCode;
import com.tarena.lbs.business.constant.BusinessTypes;
import com.tarena.lbs.business.dao.repository.BusinessRepository;
import com.tarena.lbs.business.pojo.param.BusinessParam;
import com.tarena.lbs.business.pojo.po.BusinessPO;
import com.tarena.lbs.business.pojo.query.BusinessQuery;
import com.tarena.lbs.business.pojo.vo.BusinessStoreVO;
import com.tarena.lbs.business.pojo.vo.BusinessVO;
import com.tarena.lbs.business.servcie.BusinessService;
import com.tarena.lbs.common.enums.Roles;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class BusinessServiceImpl implements BusinessService {
    @Autowired
    private BusinessRepository businessRepository;
    @DubboReference
    private AttachApi attachApi;
    @DubboReference
    private BusinessApi businessApi;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    // 新增商家
    @Override
    public void save(BusinessParam param) throws BusinessException {  // 修改：异常类型改为BusinessServiceException
        log.debug("保存商家信息，入参：{}", param);
        // 1.检查当前登录用户的角色是否符合要求
        checkRole(Roles.ADMIN);
        // 2.验证幂等性（是否存在相同名称的商家）
        String businessName = param.getBusinessName();
        BusinessPO existingPO = businessRepository.findByBusinessName(businessName);
        if (existingPO != null) {
            // 如果已存在同名商家，抛出异常
            throw new BusinessServiceException(StatusCode.BUSINESS_NAME_DUPLICATE);
        }
        // 3.新增商家
        Integer id = saveBusiness(param);
        // 4.绑定图片
        bindPictures(id, param);
    }

    private Integer saveBusiness(BusinessParam param) {
        BusinessPO businessPO = new BusinessPO();
        BeanUtils.copyProperties(param, businessPO);
        businessRepository.saveParam(businessPO);
        return businessPO.getId();
    }

    private void bindPictures(Integer businessId, BusinessParam param) throws BusinessException {  // 修改：异常类型
        List<PicUpdateParam> picParams = new ArrayList<>();
        // 营业执照参数
        PicUpdateParam licenseParam = new PicUpdateParam();
        licenseParam.setBusinessType(BusinessTypes.BIZ_LICENSE);
        licenseParam.setBusinessId(businessId);
        String licenseUrl = param.getBusinessLicense();
        licenseParam.setFileUuid(getFileUuidFromUrl(licenseUrl));
        // Logo参数
        PicUpdateParam logoParam = new PicUpdateParam();
        logoParam.setBusinessType(BusinessTypes.BIZ_LOGO);
        logoParam.setBusinessId(businessId);
        String logoUrl = param.getBusinessLogo();
        logoParam.setFileUuid(getFileUuidFromUrl(logoUrl));
        // 批量绑定
        picParams.add(licenseParam);
        picParams.add(logoParam);
        boolean result = attachApi.batchUpdateBusiness(picParams);
        Asserts.isTrue(
                !result,
                new BusinessServiceException(StatusCode.BUSINESS_BIND_FAILED)
        );
    }

    private String getFileUuidFromUrl(String licenseUrl) {
        if (licenseUrl == null || licenseUrl.isEmpty()) {
            return null;
        }
        int lastSlashIndex = licenseUrl.lastIndexOf("/");
        if (lastSlashIndex >= 0 && lastSlashIndex < licenseUrl.length() - 1) {
            return licenseUrl.substring(lastSlashIndex + 1);
        }
        return licenseUrl;
    }

    private void checkRole(Roles roles) throws BusinessServiceException {  // 修改：异常类型
        if (!Roles.ADMIN.equals(roles)) {
            throw new BusinessServiceException(StatusCode.NO_ADMIN_PERMISSION);
        }
    }

    // 查询商家列表
    @Override
    public PageResult<BusinessVO> getBusinessList(BusinessQuery query) {
        log.debug("查询商家列表，入参：{}", query);
        // 1. 生成唯一缓存Key（根据查询参数拼接，确保不同条件缓存不冲突）
        // 示例：business:list:name=xxx:status=1:pageNo=1:pageSize=10
        String cacheKey = "business:list:" +
                "name=" + (query.getBusinessName() == null ? "null" : query.getBusinessName()) +
                ":phone=" + (query.getBusinessHeadPhone() == null ? "null" : query.getBusinessHeadPhone()) +
                ":status=" + (query.getBusinessStatus() == null ? "null" : query.getBusinessStatus()) +
                ":start=" + (query.getStartingTime() == null ? "null" : query.getStartingTime().toString()) +
                ":end=" + (query.getEndTime() == null ? "null" : query.getEndTime().toString()) +
                ":id=" + (query.getBusinessId() == null ? "null" : query.getBusinessId()) +
                ":pageNo=" + query.getPageNo() +
                ":pageSize=" + query.getPageSize();

        // 2. 先查Redis缓存
        String cacheValue = (String) redisTemplate.opsForValue().get(cacheKey);
        if (cacheValue != null) {
            // 缓存命中：直接将JSON字符串转回PageResult对象并返回
            log.debug("缓存命中，key：{}", cacheKey);
            return JSON.parseObject(cacheValue, new TypeReference<PageResult<BusinessVO>>() {});
        }

        // 3. 缓存未命中：调用仓储层查数据库
        PageResult<BusinessVO> result = businessRepository.getBusinessList(query);

        // 4. 将数据库查询结果存入Redis，设置5分钟过期（300秒）
        if (result != null) {
            redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(result), 300, TimeUnit.SECONDS);
            log.debug("缓存已更新，key：{}，过期时间：5分钟", cacheKey);
        }

        return result;
    }

    // 根据商家id查询详情
    @Override
    public BusinessStoreVO selectBusinessStoreDetail(Integer businessId) throws BusinessException {  // 修改：异常类型
        log.debug("查询商家详情:{}", businessId);
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        log.debug("userPrinciple:{}", userPrinciple);
        // 校验用户是否登录
        Asserts.isTrue(
                userPrinciple != null,
                new BusinessServiceException(StatusCode.AUTH_PARSE_ERROR)
        );
        // 校验角色权限
        Roles userRole = userPrinciple.getRole();
        Asserts.isTrue(
                Roles.ADMIN.equals(userRole) || Roles.SHOP.equals(userRole),
                new BusinessServiceException(StatusCode.NO_BUSINESS_DETAIL_PERMISSION)
        );
        return businessRepository.selectBusinessStore(businessId);
    }

    @Override
    public BusinessDto getBusinessById(Integer businessId) throws BusinessException {
        return businessRepository.getBusinessById(businessId);
    }


}
